﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SilverLightStreamingInterface;
using System.IO;

namespace t_SSI
{
    /// <summary>
    /// Summary description for t_SLLiveInterface
    /// </summary>
    [TestClass]
    public class t_SLLiveInterface
    {
        public t_SLLiveInterface()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void TestForApp()
        {
            Utilities.accountInfo info = Utilities.GetAccountInfo();
            SLLiveInterface live = new SLLiveInterface(info.id, info.key);
            Assert.IsTrue(live.PackageExists("TestApp"), "Package TestApp should already exist!");
        }

        [TestMethod]
        public void CreateAndDeleteApp()
        {
            Utilities.accountInfo info = Utilities.GetAccountInfo();
            SLLiveInterface live = new SLLiveInterface(info.id, info.key);

            ///
            /// Delete an app if it is there
            /// 

            if (live.PackageExists("BogusApp"))
            {
                live.RemovePackage("BogusApp");
            }
            Assert.IsFalse(live.PackageExists("BogusApp"), "Package TestApp should already exist!");
            live.CreatePackage("BogusApp");
            Assert.IsTrue(live.PackageExists("BogusApp"), "Package TestApp should already exist!");
            live.RemovePackage("BogusApp");
            Assert.IsFalse(live.PackageExists("BogusApp"), "Package TestApp should already exist!");
        }

        [TestMethod]
        public void CreateProvisionedApp()
        {
            Utilities.accountInfo info = Utilities.GetAccountInfo();
            SLLiveInterface live = new SLLiveInterface(info.id, info.key);
   
            ///
            /// Delete the app if it is there
            /// 

            string pkgName = "TestCreatedProvisionedApp";
            if (live.PackageExists(pkgName))
            {
                live.RemovePackage(pkgName);
            }

            FileInfo manifestFile = new FileInfo(@"..\..\..\t_SilverLightStreamingInterface\manifest.xml");
            Assert.IsTrue(manifestFile.Exists, "Manifest file is missing! Can't do this test!");
            live.CreateProvisionedPackage(pkgName, manifestFile);
            Assert.IsTrue(live.PackageExists(pkgName));
        }

        [TestMethod]
        public void TestSingleFileOps()
        {
            /// Dummy package.
            DirectoryInfo project = new DirectoryInfo(Path.GetTempPath() + "\\TestSingleFilesOps");
            if (!project.Exists)
            {
                project.Create();
            }
            FileInfo onefile = new FileInfo(project.FullName + "\\test.txt");
            using (TextWriter wr = onefile.CreateText())
            {
                wr.WriteLine("hi");
                wr.Close();
            }

            Utilities.accountInfo info = Utilities.GetAccountInfo();
            SLLiveInterface live = new SLLiveInterface(info.id, info.key);
            SLPackage pack = new SLPackage("TestSingleFileOps") { PackageDirectory = project };
            if (live.PackageExists(pack))
            {
                live.RemovePackage(pack);
            }
            live.CreatePackage(pack);

            Assert.IsFalse(live.FileExists(pack, onefile), "Single upload file seems to already be there");
            live.UploadSingleFile(pack, onefile);
            Assert.IsTrue(live.FileExists(pack, onefile), "Single upload file seems to be missing");
        }

        [TestMethod]
        public void TestUploadBadFile()
        {
            /// Dummy package.
            DirectoryInfo project = new DirectoryInfo(Path.GetTempPath() + "\\TestUploadBadFile");
            if (!project.Exists)
            {
                project.Create();
            }
            FileInfo onefile = new FileInfo(project.FullName + "\\test.html");
            using (TextWriter wr = onefile.CreateText())
            {
                wr.WriteLine("hi");
                wr.Close();
            }

            Utilities.accountInfo info = Utilities.GetAccountInfo();
            SLLiveInterface live = new SLLiveInterface(info.id, info.key);
            SLPackage pack = new SLPackage("TestUploadBadFile") { PackageDirectory = project };
            if (live.PackageExists(pack))
            {
                live.RemovePackage(pack);
            }
            live.CreatePackage(pack);

            Assert.IsFalse(live.FileExists(pack, onefile), "Single upload file seems to already be there");
            live.UploadSingleFile(pack, onefile);
            Assert.IsFalse(live.FileExists(pack, onefile), "Single upload file should never have been uploaded!");
        }

        [TestMethod]
        public void TestSubDir()
        {
            /// Dummy package.
            DirectoryInfo project = new DirectoryInfo(Path.GetTempPath() + "\\TestSubDir");
            if (!project.Exists)
            {
                project.Create();
            }
            DirectoryInfo subdir = new DirectoryInfo(project.FullName + "\\subdir");
            if (!subdir.Exists)
            {
                subdir.Create();
            }

            FileInfo onefile = new FileInfo(subdir.FullName + "\\test.txt");
            using (TextWriter wr = onefile.CreateText())
            {
                wr.WriteLine("hi");
                wr.Close();
            }

            Utilities.accountInfo info = Utilities.GetAccountInfo();
            SLLiveInterface live = new SLLiveInterface(info.id, info.key);
            SLPackage pack = new SLPackage("TestSubDir") { PackageDirectory = project };
            if (live.PackageExists(pack))
            {
                live.RemovePackage(pack);
            }
            live.CreatePackage(pack);

            Assert.IsFalse(live.FileExists(pack, onefile), "Single upload file seems to already be there");
            try
            {
                live.UploadSingleFile(pack, onefile);
                Assert.Fail("Upload of file should have failed, but it didn't!");
            }
            catch
            {
            }

            Assert.IsFalse(live.SubDirExists(pack, subdir), "Directory should not exist yet!");
            live.CreateDirectory(pack, subdir);
            live.UploadSingleFile(pack, onefile);
            Assert.IsTrue(live.FileExists(pack, onefile), "Single upload file seems to be missing");

            /// Make sure re-creating the subdir doesn't cause ill side effects
            Assert.IsTrue(live.SubDirExists(pack, subdir), "Directory should exist, but it does not");
            Assert.IsTrue(live.FileExists(pack, onefile), "Single upload file seems to be missing");
        }

        [TestMethod]
        public void UploadZipFile()
        {
            Utilities.accountInfo info = Utilities.GetAccountInfo();
            SLLiveInterface live = new SLLiveInterface(info.id, info.key);

            DirectoryInfo project = Utilities.GetSLTalk();

            SLPackage pack = new SLPackage("BogusApp") { PackageDirectory = project };
            PackagePrep prep = new PackagePrep();
            prep.CleanPackage(pack);
            var zipped = prep.ZipPackage(pack);

            if (live.PackageExists(pack.Name))
            {
                live.RemovePackage(pack.Name);
            }
            live.CreatePackage(pack);
            live.UploadPackageZIP(pack);
            Assert.IsTrue(live.PackageExists("BogusApp"), "Package Bogus App should already exist!");
        }

        [TestMethod]
        public void UploadByFiles()
        {
            ///
            /// Given a directory structure down here, see if we can upload stuff!
            /// 

            DirectoryInfo dir = new DirectoryInfo(Path.GetTempPath() + "\\UploadByFiles");
            if (dir.Exists)
            {
                dir.Delete(true);
            }
            dir.Create();

            FileInfo lastone = null;
            for (int i = 0; i < 10; i++)
            {
                FileInfo f = new FileInfo(dir.FullName + "\\test-" + i.ToString() + ".txt");
                lastone = f;
                using (TextWriter wr = f.CreateText())
                {
                    wr.WriteLine("hi");
                    wr.Close();
                }
            }

            ///
            /// Make sure that is all cleared in the file cache so we can upload again without errors
            /// 

            FileUploadStateCache_Accessor fc = new FileUploadStateCache_Accessor();
            fc.GetCacheForDirectory(lastone.DirectoryName).Clear();

            ///
            /// Hook up to the SL service.
            /// NOTE: we should not throw inside one of the UploadPackage callbacks. The reason is pretty simple:
            /// we don't want to have to deal with a totally messy reporting. Since the upload is often multithreaded,
            /// when we throw the argument exceptions come back funny because they are wrapped in the multi-exception
            /// guy.
            /// 

            Utilities.accountInfo info = Utilities.GetAccountInfo();
            SLLiveInterface live = new SLLiveInterface(info.id, info.key);

            SLPackage pack = new SLPackage("TestUploadByFiles") { PackageDirectory = dir };

            if (live.PackageExists(pack))
            {
                live.RemovePackage(pack);
            }
            live.CreatePackage(pack);

            int count=0;
            live.UploadPackage(pack, (fname, ok) => { if (ok) count = count + 1;});
            Assert.IsTrue(count == 10, "Wrong number of uploads completed!");

            count = 0;

            live.UploadPackage(pack, (fname, ok) => { if (ok) count = count + 1; });
            Assert.IsTrue(count == 0, "More files were uploaded the second time around - bad!");

            ///
            /// Modify one file and see that it goes up
            /// 

            lastone.LastWriteTime = DateTime.Now;
            live.UploadPackage(pack, (fname, ok) => { if(ok) count = count + 1; });
            Assert.IsTrue(count == 1, "Modified file was not written back or more than that one file was written up.");

            ///
            /// Finally, make sure the files are actually up there on the service!
            /// 

            Assert.IsTrue(live.FileExists(pack, lastone), "Single upload file seems to be missing");

            ///
            /// Create a subdirectory and try again
            /// 

            DirectoryInfo newdir = new DirectoryInfo(dir.FullName + "\\subdir");
            if (!newdir.Exists)
            {
                newdir.Create();
            }
            FileInfo newfile = new FileInfo(newdir + "\\test.txt");
            using (TextWriter wr = newfile.CreateText())
            {
                wr.WriteLine("hi");
                wr.Close();
            }
            fc.GetCacheForDirectory(newfile.DirectoryName).Clear();

            count = 0;
            live.UploadPackage(pack, (fname, ok) => { if(ok) count = count + 1; });
            Assert.IsTrue(count == 1, "Shoudl have only uploaded a single file in the subdir!");
        }
    }
}
